import type { RouteObjectType } from "@/typings/router";
import type { RequestData, ResPage } from "@/typings/proTable";
import { message } from "@/hooks/modules/useToast";
import Decimal from "decimal.js";

/**
 * @description checkStatus 校验网络请求状态码
 * @param {string | number} status
 * @author 花东红
 * @time 2025/8/7
 */
export const checkStatus = (status: string | number) => {
  const codeMap: Record<string, string> = {
    400: "请求失败！请您稍后重试",
    403: "当前账号无权限访问！",
    404: "你所访问的接口不存在！",
    405: "请求方式错误，请您稍后重试",
    408: "请求超时，请您稍后重试",
    500: "服务异常，请您稍后重试",
    502: "网关错误，请您稍后重试",
    503: "服务不可用，请您稍后重试",
    504: "网关超时，请您稍后重试"
  };
  if (codeMap[status]) {
    message.error(codeMap[status]).then(() => {});
    return;
  }
  message.error("请求失败，请您稍后重试").then(() => {});
};

/**
 * @description 获取当前时间对应的提示语
 * @returns {string | undefined}
 */
export const getTimeState = (): string | undefined => {
  const timeNow = new Date();
  const hours = timeNow.getHours();
  if (hours >= 6 && hours <= 10) return `早上好 ⛅`;
  if (hours >= 10 && hours <= 14) return `中午好 🌞`;
  if (hours >= 14 && hours <= 18) return `下午好 🌞`;
  if (hours >= 18 && hours <= 24) return `晚上好 🌛`;
  if (hours >= 0 && hours <= 6) return `凌晨好 🌛`;
};

/**
 * @description 获取第一级菜单
 * @param {RouteObjectType[]} menuList 后端返回的权限路由数据.
 */
export const getFirstLevelMenuList = (menuList: RouteObjectType[]) => {
  return menuList.map((item) => ({ ...item, children: undefined }));
};

/**
 * @description 将 3 位十六进制颜色代码转换为 6 位代码.
 */
export const convertToSixDigitHexColor = (str: string) => {
  if (str.length > 4) return str.toLocaleUpperCase();
  return (str[0] + str[1] + str[1] + str[2] + str[2] + str[3] + str[3]).toLocaleUpperCase();
};

/**
 * @description: 是否为十六进制颜色
 */
export const isHexColor = (str: string) => {
  return /^#?([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6})$/.test(str);
};

/**
 * @description 使用参数获取相对url
 */
export const getUrlWithParams = () => {
  const url: Record<string, string> = {
    hash: location.hash.substring(1),
    history: location.pathname + location.search
  };
  return url[import.meta.env.VITE_APP_ROUTER_MODE];
};

/**
 * @description 获取需要展开的 subMenu 键
 * @param {string} path 当前路径
 */
export const getOpenKeys = (path: string) => {
  let currentKey: string = "";
  let openKeys: string[] = [];
  let pathSegments: string[] = path.split("/").map((segment: string) => "/" + segment);
  for (let i: number = 1; i < pathSegments.length - 1; i++) {
    currentKey += pathSegments[i];
    openKeys.push(currentKey);
  }
  return openKeys;
};

/**
 * @description 设置样式属性
 * @param {string} key style 属性的键名称
 * @param {string} val style 属性的值
 */
export const setStyleProperty = (key: string, val: string) => {
  document.documentElement.style.setProperty(key, val);
};

/**
 * @description 验证是否为blob格式
 * @param {Blob} data 传入Content-Type
 */
export const blobValidate = (data: Blob) => {
  return data.type !== "application/json";
};

/**
 * @description 过滤掉请求参数键值对中值为空的项
 * @param {Record<string, any>} data 接口请求参数
 * @author 花东红
 * @time 2024/7/15
 */
export const useFilterEmptyParams = (data: Record<string, any>) => {
  if (!Object.keys(data).length) return {};
  return Object.entries(data).reduce((acc, [key, value]) => {
    if (value !== null && value !== undefined && value !== "") {
      // @ts-expect-error check value type
      acc[key] = value;
    }
    return acc;
  }, {});
};

/**
 * @description 生成随机数
 * @param {number} min 最小值
 * @param {number} max 最大值
 */
export const useRandomNum = (min: number, max: number) => {
  return Math.floor(Math.random() * (min - max) + max);
};

/**
 * @description 千分位自动补逗号
 * @param {string | number} num 传入需转换的数据
 */
export const useFormatNumber = (num: string | number) => {
  if (!num) return;
  return num.toString().replace(/\d+/, function (n) {
    return n.replace(/(\d)(?=(?:\d{3})+$)/g, "$1,");
  });
};

/**
 * @description 截取字符串指定项后面的内容
 * @param {string} str 传入的字符串
 * @param {string} key 截取关键字
 */
export const useStrCaption = (str: string, key: string) => {
  const index = str.lastIndexOf(key);
  return str.substring(index + 1, str.length);
};

/**
 * @description 一维数组求和
 * @param {Array} arr 传入一维数组，示例arr:[{num:1},{num:2}]
 * @param {string} key 传入对象中需要相加的key参数,key:num
 * @param {number} precision 小数位数
 */
export const useArraySumWithKey = (arr: any[], key: string, precision: number = 2) => {
  return arr.reduce(function (total, value) {
    return new Decimal(total).add(new Decimal(value[key])).toFixed(precision);
  }, 0);
};

/**
 * @description 一维数组求和
 * @param {Array} arr 传入需要求和的数组，示例：[1,2,3,4,5]
 */
export const useArraySum = (arr: any[]) => {
  return arr.reduce((total, value) => new Decimal(total).add(new Decimal(value)).toString(), 0);
};

/**
 * @description 根据接口枚举数据 匹配出中文名称
 * @param {any[]} enumList 接口枚举
 * @param {string | number} field 枚举值
 * @param {string} [key] 指定 key 键
 * @param {string} [value] 指定 value 键
 * @author 花东红
 * @time 2024/11/22
 */
export const useEnumeratePicker = (enumList: any[], field: string | number, key?: string, value?: string) => {
  if (!enumList) return;
  const matchItem = enumList.find((item: Record<string, any>) => item[value ?? "value"] === field) || {};
  return matchItem[key ?? "label"] || "";
};

/**
 * @description 处理日期参数
 * @param {Record<string, any>} data
 * @author 花东红
 * @time 2024/7/15
 */
export const useFormatDateParams = (data: Record<string, any>) => {
  if (!Object.keys(data.params).length) return {};
  const paramsObj = JSON.parse(JSON.stringify(data.params));
  delete paramsObj[data.labelName];
  if (data.params[data.labelName] && data.params[data.labelName].length) {
    return {
      [data.startTimeName ?? "startTime"]: data.params[data.labelName][0].format("YYYY-MM-DD 00:00:00"),
      [data.endTimeName ?? "endTime"]: data.params[data.labelName][1].format("YYYY-MM-DD 23:59:59"),
      ...paramsObj
    };
  }

  return {
    ...data.initialValue,
    ...paramsObj
  };
};

/**
 * @description 格式化后端返回的 ProTable 组件数据.
 * @param {Object} data - The data returned by the server.
 * @returns {Object}
 */
export function formatDataForProTable<T>(data: ResPage<T>): Partial<RequestData<T>> {
  return {
    success: true,
    data: data.list,
    total: data.total
  };
}
